package fr.kraml;

import java.util.ArrayList;
import java.util.Iterator;

import fr.kraml.LoginFragment.LoginFragmentListener;
import fr.kraml.ParticipantFragment.ParticipantFragmentListener;
import fr.kraml.RoomFragment.RoomFragmentListener;
import fr.kraml.adapter.TabsPagerAdapter;
import android.os.*;
import android.annotation.SuppressLint;
import android.app.*;
import android.app.ActionBar.Tab;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.*;
import android.widget.*;

public class KramlMain extends FragmentActivity implements
		ActionBar.TabListener, LoginFragmentListener, RoomFragmentListener,
		ParticipantFragmentListener {

	// Messages reçus du service !
	static final int MSG_ALL_CONNECTED = 10000;
	static final int MSG_TOAST = 10001;
	static final int MSG_CONNECTED = 10002;
	static final int MSG_ROOM_LIST = 10003;
	static final int MSG_ROOM_INFO = 10004;
	static final int MSG_GROUPCHAT = 10005;
	static final int MSG_PRESENCE = 10006;
	static final int MSG_DISCONNECTED = 10007;

	// private ViewPager viewPager;
	private TabsPagerAdapter loginAdapter, chatAdapter;
	private ActionBar actionBar;
	private ViewPager loginVP, chatVP;

	// Messenger pour la communication avec le service
	Messenger mService = null;
	// Mon service est-il bindé ?
	boolean mIsBound;

	final Messenger mMessenger = new Messenger(new IncomingHandler());

	public ArrayList<ASV> asv_cache = new ArrayList<ASV>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_kraml_main);

		// Initialization
		// viewPager = (ViewPager) findViewById(R.id.pager);
		actionBar = getActionBar();
		loginVP = (ViewPager) findViewById(R.id.pagerLogin);
		loginVP.setVisibility(View.GONE);
		chatVP = (ViewPager) findViewById(R.id.pagerChat);
		chatVP.setVisibility(View.GONE);
		// mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
		loginAdapter = new TabsPagerAdapter(getSupportFragmentManager(),
				loginVP, actionBar);
		chatAdapter = new TabsPagerAdapter(getSupportFragmentManager(), chatVP,
				actionBar);
		// viewPager.setAdapter(mAdapter);
		// actionBar.setHomeButtonEnabled(false);
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

		// Init Login Form
		// initLoginForm();

		/**
		 * on swiping the viewpager make respective tab selected
		 * */
		/*
		 * viewPager.setOnPageChangeListener(new
		 * ViewPager.OnPageChangeListener() {
		 * 
		 * @Override public void onPageSelected(int position) { // on changing
		 * the page // make respected tab selected
		 * actionBar.setSelectedNavigationItem(position); }
		 * 
		 * @Override public void onPageScrolled(int arg0, float arg1, int arg2)
		 * { }
		 * 
		 * @Override public void onPageScrollStateChanged(int arg0) { } });
		 */

		// Demarrage du service si pas démarré
		if (!KramlService.isRunning()) {
			Intent intent = new Intent(this, KramlService.class);
			startService(intent);
		}

		// Bind du service (pour recevoir des messages)
		doBindService();

	}

	private void initLoginForm() {
		chatVP.setVisibility(View.GONE);
		actionBar.removeAllTabs();
		loginAdapter.addFragment(new LoginFragment(), "Login");
		// loginAdapter.addFragment(new RegisterFragment(), "Register");
		loginVP.setVisibility(View.VISIBLE);
	}

	public void initChat() {
		loginVP.setVisibility(View.GONE);
		// TODO Auto-generated method stub
		// actionBar.removeAllTabs();
		// mAdapter.removePages();
		// mAdapter.notifyDataSetChanged();
		// mAdapter.destroyItem(viewPager, 0, mAdapter.getItem(0));
		// mAdapter.mActionBar.removeAllTabs();
		// mAdapter.destroyItem(viewPager, 0, mAdapter.getItem(0));
		// actionBar.addTab(actionBar.newTab().setText("Room").setTabListener(this));
		// mAdapter.mPager.getChildAt(0).setVisibility(View.GONE);
		// mAdapter.addFragment(new RoomFragment(), "Room");
		// actionBar.addTab(actionBar.newTab().setText("PV1").setTabListener(this));
		// mAdapter.addFragment(new PVFragment(), "PV1");
		// mAdapter.notifyDataSetChanged();
		actionBar.removeAllTabs();
		// chatAdapter.notifyDataSetChanged();
		chatAdapter.addFragment(new ParticipantFragment(), "Participants");
		chatAdapter.addFragment(new RoomFragment(), "Room");
		// chatAdapter.notifyDataSetChanged();
		// actionBar.addTab(actionBar.newTab().setText("Register").setTabListener(this));
		chatAdapter.addFragment(new PVFragment(), "PV1");
		// chatAdapter.notifyDataSetChanged();
		chatAdapter.mPager.setCurrentItem(1);
		chatVP.setVisibility(View.VISIBLE);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Menu des options (en haut à droite)
		getMenuInflater().inflate(R.menu.kraml_main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Actions des options du Menu
		switch (item.getItemId()) {
		// Bouton exit
		case R.id.action_exit:
			// Disconnect
			// disconnect();

			// Arrêt du service
			Intent intent = new Intent(this, KramlService.class);
			stopService(intent);
			finish();

			return true;
		case R.id.action_disconnect:
			disconnect();
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	private void disconnect() {
		// TODO Auto-generated method stub
		Message msg = Message.obtain(null, KramlService.MSG_LOGOUT);
		try {
			mService.send(msg);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void onTabReselected(Tab tab, FragmentTransaction ft) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onTabSelected(Tab tab, FragmentTransaction ft) {
		// TODO Auto-generated method stub
		// viewPager.setCurrentItem(tab.getPosition());
	}

	@Override
	public void onTabUnselected(Tab tab, FragmentTransaction ft) {
		// TODO Auto-generated method stub

	}

	private ServiceConnection mConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName className, IBinder service) {
			// This is called when the connection with the service has been
			// established, giving us the service object we can use to
			// interact with the service. We are communicating with our
			// service through an IDL interface, so get a client-side
			// representation of that from the raw service object.

			mService = new Messenger(service);

			try {
				Message msg = Message.obtain(null, KramlService.MSG_MESSAGE);
				msg.replyTo = mMessenger;
				mService.send(msg);
			} catch (RemoteException e) {
				// In this case the service has crashed before we could even do
				// anything with it
			}

			// mService = new Messenger(service);
			// mCallbackText.setText("Attached.");

			// We want to monitor the service for as long as we are
			// connected to it.
			/*
			 * try { Message msg = Message.obtain(null, 0); msg.replyTo =
			 * mMessenger; mService.send(msg);
			 * 
			 * // Give it some value as an example. msg = Message.obtain(null,
			 * 1, this.hashCode(), 0); mService.send(msg); } catch
			 * (RemoteException e) { // In this case the service has crashed
			 * before we could even // do anything with it; we can count on soon
			 * being // disconnected (and then reconnected if it can be
			 * restarted) // so there is no need to do anything here. }
			 */

			// As part of the sample, tell the user what happened.
			Toast.makeText(KramlMain.this, "connected", Toast.LENGTH_SHORT)
					.show();

			Message msg = Message.obtain(null, KramlService.GET_ALL);
			try {
				mService.send(msg);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onServiceDisconnected(ComponentName className) {
			// This is called when the connection with the service has been
			// unexpectedly disconnected -- that is, its process crashed.
			mService = null;
			// mCallbackText.setText("Disconnected.");

			// As part of the sample, tell the user what happened.
			Toast.makeText(KramlMain.this, "Disconnected", Toast.LENGTH_SHORT)
					.show();

			// On quitte l'appli
			System.exit(0);
		}
	};

	@SuppressLint("HandlerLeak")
	class IncomingHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MSG_TOAST:
				/*
				 * KramlParcelableLogin data = (KramlParcelableLogin) msg
				 * .getData().getParcelable("toast");
				 */
				String str = msg.getData().getString("TOAST");
				showToast(str, Toast.LENGTH_LONG);
				Log.i("KramL", str);
				break;
			case MSG_CONNECTED:
				/*
				 * Intent myIntent = new Intent(KramlMain.this,
				 * KramlChat.class); // myIntent.putExtra("key", value);
				 * //Optional parameters Log.i("KramlMain",
				 * "Connect Received, launch KramlChat");
				 * KramlMain.this.startActivity(myIntent);
				 * 
				 * // joinRoom("Nouveaux Venus");
				 */
				initChat();
				break;
			case MSG_DISCONNECTED:
				initLoginForm();
				break;
			case MSG_ROOM_LIST:
				LoginFragment lf = (LoginFragment) loginAdapter.getItem(0);
				String room_list = msg.getData().getString("room_list");
				Log.i("KramlMain", "Room list received : " + room_list);
				lf.majRoomList(room_list);
				break;
			case MSG_ALL_CONNECTED:
				boolean connected = msg.getData().getBoolean("connected");
				if (connected)
					initChat();
				else
					initLoginForm();
				break;
			case MSG_ROOM_INFO:
				String room_name = msg.getData().getString("room_name");
				actionBar.getTabAt(1).setText(room_name);
				Log.i("KramlMain", "Set room name @ : " + room_name);
				break;
			case MSG_GROUPCHAT:
				RoomFragment rf = (RoomFragment) chatAdapter.getItem(1);
				String mess_from = msg.getData().getString("from");
				String text = msg.getData().getString("text");
				String color = msg.getData().getString("color");
				Log.i("KramlMain", "Groupchat recu : " + mess_from + " > "
						+ text);
				rf.displayMessage(mess_from, text, color);
				break;
			case MSG_PRESENCE:
				ParticipantFragment pf = (ParticipantFragment) chatAdapter
						.getItem(0);
				String pres_from = msg.getData().getString("from");
				String show = msg.getData().getString("show");
				String status = msg.getData().getString("status");
				String age = msg.getData().getString("age");
				String sex = msg.getData().getString("sex");
				String location = msg.getData().getString("location");
				String avatar = msg.getData().getString("avatar");
				add_asv_cache(pres_from, Integer.parseInt(age), sex, location);
				pf.changeParticipant(pres_from, show, status,
						Integer.parseInt(age), sex, location, avatar);

				if (! msg.getData().containsKey("BDD")) {
					rf = (RoomFragment) chatAdapter.getItem(1);
					mess_from = msg.getData().getString("from");
					show = msg.getData().getString("show");
					rf.displayPresence(mess_from, show);
				}
				break;
			default:
				super.handleMessage(msg);
			}
		}
	}

	void doBindService() {
		// Establish a connection with the service. We use an explicit
		// class name because there is no reason to be able to let other
		// applications replace our component.
		getApplicationContext().bindService(
				new Intent(KramlMain.this, KramlService.class), mConnection,
				Context.BIND_AUTO_CREATE);
		mIsBound = true;

		// mCallbackText.setText("Binding.");
	}

	public void showToast(String txt, int length) {
		Toast toast = Toast.makeText(this, txt.toString(), length);
		toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0);
		toast.show();
	}

	@Override
	public void onLoginPressed(String user, String pass, String roomname) {
		Bundle b = new Bundle();
		b.putString("user", user);
		b.putString("password", pass);
		b.putString("room", roomname);
		Message msg = Message.obtain(null, KramlService.MSG_LOGIN);
		msg.setData(b);
		try {
			mService.send(msg);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void joinRoom(String room) {
		Bundle b = new Bundle();
		b.putString("room", room);
		Message msg = Message.obtain(null, KramlService.MSG_JOIN_ROOM);
		msg.setData(b);
		try {
			mService.send(msg);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void majRoomListLoginFragment() {
		// TODO Auto-generated method stub
		Message msg = Message.obtain(null, KramlService.MSG_ROOM_LIST);
		try {
			mService.send(msg);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void onGroupChatSend(String text) {
		// TODO Auto-generated method stub
		Bundle b = new Bundle();
		b.putString("text", text);
		Message msg = Message.obtain(null, KramlService.MSG_GROUPCHAT);
		msg.setData(b);
		try {
			mService.send(msg);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void add_asv_cache(String from, int age, String sex, String location) {
		// TODO Auto-generated method stub
		Iterator<ASV> i = asv_cache.iterator();
		while (i.hasNext()) {
			ASV asv = (ASV) i.next();
			if (asv.username.equals(from)) {
				asv.age = age;
				asv.sex = sex;
				asv.location = location;
				return;
			}
		}
		asv_cache.add(new ASV(from, age, sex, location));
	}

	@Override
	public ASV getASV(String username) {
		// TODO Auto-generated method stub
		Iterator<ASV> i = asv_cache.iterator();
		while (i.hasNext()) {
			ASV asv = (ASV) i.next();
			if (asv.username.equals(username))
				return asv;
		}
		return new ASV(username, 0, "X", "Nowhere");
	}

	@Override
	public void loadBDDMessages() {
		// TODO Auto-generated method stub
		Message msg = Message.obtain(null, KramlService.MSG_LOAD_BDD_MESSAGES);
		try {
			mService.send(msg);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void loadBDDParticipants() {
		// TODO Auto-generated method stub
		Message msg = Message.obtain(null,
				KramlService.MSG_LOAD_BDD_PARTICIPANTS);
		try {
			mService.send(msg);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
